package psn.kiko.service.business.system;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import psn.kiko.constant.DBConstant;
import psn.kiko.constant.MessageConstant;
import psn.kiko.excepion.BaseBusinessException;
import psn.kiko.mapper.business.system.OperationMapper;
import psn.kiko.pojo.dto.OperationDTO;
import psn.kiko.pojo.entity.system.OperationEntity;
import psn.kiko.pojo.entity.system.UserEntity;
import psn.kiko.pojo.vo.InterfaceVO;
import psn.kiko.pojo.vo.LabelValue;
import psn.kiko.pojo.vo.OperationVO;
import psn.kiko.pojo.vo.PureInterfaceVO;
import psn.kiko.pojo.vo.ui.NavigationGroupUI;
import psn.kiko.pojo.vo.ui.OperationUI;
import psn.kiko.service.business.associated.OperationInterfaceService;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 导航项操作服务
 */
@Service
public class OperationService{
	@Autowired
	OperationMapper operationMapper;
	@Resource
	OperationInterfaceService operationInterfaceService;
	
	/**
	 * 获取某一导航项的所有操作
	 */
	public List<OperationVO> getOperationsOfNavItem(Integer navItemId){
		return operationMapper.selectListByNavItemId(navItemId);
	}
	
	/**
	 * 给导航项添加一项操作
	 */
	public Integer addOperationOfNavItem(OperationDTO operationDTO,Integer navItemId){
		operationDTO.setNavigationId(navItemId);
		//操作状态检查
		if(!DBConstant.getStatuses().contains(operationDTO.getEnabled())){
			operationDTO.setEnabled(DBConstant.DISABLE);
		}
		OperationEntity operationEntity = new OperationEntity();
		BeanUtils.copyProperties(operationDTO,operationEntity);
		try{
			return operationMapper.insert(operationEntity);
		}catch(DuplicateKeyException e){
			throw new BaseBusinessException(MessageConstant.INSERT_DUPLICATE_ROWS);
		}
	}
	
	/**
	 * 更新操作
	 */
	public Integer updateOperation(OperationDTO operationDTO){
		if(!DBConstant.getStatuses().contains(operationDTO.getEnabled())){
			operationDTO.setEnabled(DBConstant.DISABLE);
		}
		OperationEntity operationEntity = new OperationEntity();
		BeanUtils.copyProperties(operationDTO,operationEntity);
		return operationMapper.updateById(operationEntity);
	}
	
	/**
	 * 根据主键删除一批操作,并删除关联的接口
	 */
	public Integer deleteOperations(List<Integer> opIds){
		//删除 操作-接口 中间表数据
		operationInterfaceService.unAllocateApisOfOperations(opIds);
		return operationMapper.batchDeleteById(opIds);
	}
	
	/**
	 * 根据主键启用一批操作
	 */
	public Integer batchEnableOperations(List<Integer> opIds){
		return operationMapper.updateStatusByIds(opIds,DBConstant.ENABLE);
	}
	
	/**
	 * 根据主键禁用一批操作
	 */
	public Integer batchDisableOperations(List<Integer> opIds){
		return operationMapper.updateStatusByIds(opIds,DBConstant.DISABLE);
	}
	
	/**
	 * 根据主键获取操作
	 */
	public OperationVO getOperation(Integer operationId){
		return operationMapper.selectById(operationId);
	}
	
	/**
	 * 删除一批与导航项id关联的操作
	 */
	public Integer batchDeleteWhereNavidsIn(List<Integer> navIds){
		return operationMapper.batchDeleteByNavId(navIds);
	}
	
	/**
	 * 获取所有接口选项
	 */
	public List<LabelValue> getAllInterfaceSelection(){
		return operationMapper.selectAllInterfaceSelection();
	}
	
	/**
	 * <p style="color:red;font-size:14px">UI权限核心方法</p>
	 * 并转换为三层树形结构（导航组->导航项->操作）
	 */
	public Map<String,Object> getAvailableUIAuthsOfEditableUser(UserEntity userEntity){
		String id = "id";
		String label = "label";
		String title = "title";
		String iconClass = "iconClass";
		String finalStatus = "finalStatus";
		String associatedApis = "associatedApis";
		String navigationList = "navigationList";
		String operationMap = "operation";
		String authValidateIsNeeded="authValidateIsNeeded";
		List<NavigationGroupUI> cascadeData = operationMapper.selectAvailableUIAuthsOfUser(userEntity);
		//1、从底层到高层（操作——>导航项——>导航组）逐层计算每层的最终可用状态
		cascadeData.forEach(group->{
			group.getChildren().forEach(item->{
				if(userEntity.getEditable() == DBConstant.EDITABLE){
					//可编辑用户：按照实际情况计算
					item.getChildren().forEach(OperationUI::computeFinalStatus);
				}else if(userEntity.getEditable() == DBConstant.UN_EDITABLE){
					//不可编辑用户（root）:全部可用
					item.getChildren().forEach(op->op.setFinalStatus(true));
				}else{
					//其它：全部不可用
					item.getChildren().forEach(op->op.setFinalStatus(false));
				}
				item.computeFinalStatus();
			});
			group.computeFinalStatus();
		});
		
		//2、构造四层树形结构数据：导航组————>（导航组的）导航项————>（导航项的）操作————>（操作关联的、可用的）接口
		Map<String,Object> navGroupMap = new HashMap<>();
		cascadeData.forEach(g->{
			Map<String,Object> navGroup = new HashMap<>();
			navGroupMap.put(g.getLabel(),navGroup);
			
			g.getChildren().forEach(i->{
				Map<String,Object> navItem = new HashMap<>();
				navGroup.put(i.getLabel(),navItem);
				
				i.getChildren().forEach(o->{
					Map<String,Object> operation = new HashMap<>();
					operation.put(id,o.getId());
					operation.put(label,o.getLabel());
					operation.put(title,o.getTitle());
					operation.put(iconClass,o.getIconClass());
					operation.put(finalStatus,o.getFinalStatus());
					operation.put(associatedApis,o.getChildren());
					navItem.put(o.getLabel(),operation);
				});
			});
		});
		
		//导航数据：只保留导航组——>导航项的二级级联数据
		cascadeData.forEach(g->{
			// 将每个导航项的操作列表置空
			g.getChildren().forEach(i->i.setChildren(null));
		});
		
		HashMap<String,Object> map = new HashMap<>();
		//导航级联数据
		map.put(navigationList,cascadeData);
		//操作级联数据
		map.put(operationMap,navGroupMap);
		//是否需要进行权限验证
		map.put(authValidateIsNeeded,userEntity.getEditable() == DBConstant.EDITABLE);
		return map;
	}
	
	/**
	 * 给指定操作关联一批接口,关联新接口之前,先删除该操作原先关联的所有接口
	 */
	public Integer allocateApisToOperation(List<Integer> interfaceStableIds,Integer operationId){
		//先删除当前操作原先关联的所有接口
		operationInterfaceService.unAllocateApisOfOperation(null,operationId);
		if(interfaceStableIds == null||interfaceStableIds.size() <= 0){
			return 0;
		}
		//再给当前操作关联新的接口
		return operationInterfaceService.allocateApisToOperation(interfaceStableIds,operationId);
	}
	
	public List<PureInterfaceVO> getAssociatedApisOfOperation(Integer operationId){
		return operationInterfaceService.getInterfacesOfOperation(operationId);
	}
}
